package com.gis3c.sys.service.impl;

import com.gis3c.sys.dao.MenuDao;
import com.gis3c.sys.entry.po.Menu;
import com.gis3c.sys.entry.vo.AppModel;
import com.gis3c.sys.entry.vo.MenuCombination;
import com.gis3c.sys.entry.vo.MenuModel;
import com.gis3c.sys.entry.vo.MenuTreeModel;
import com.gis3c.sys.service.MenuService;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by hukekuan on 2017/12/22.
 */
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class MenuServiceImpl implements MenuService {
    @Autowired private Mapper baseMapper;
    @Autowired private MenuDao menuDao;


    @Override
    public List<MenuCombination> findMenuList(String appId) {
        List<Menu>  menuList = menuDao.findMenuList(appId);
        return getMenuCombination(menuList);
    }

    @Override
    public List<MenuCombination> findMenuListForRole(Set<String> roleIds, String appId) {
        List<MenuCombination> result = null;
        if(roleIds.size() > 0){
            List<Menu>  menuList = menuDao.findMenuListForRole(roleIds, appId);
            result = getMenuCombination(menuList);
        }else {
            result = new ArrayList<>();
        }
        return result;
    }

    @Override
    public List<MenuTreeModel> findMenuListForTree(String roleId, String appId) {
        MenuTreeModel result = new MenuTreeModel();
        result.setTitle("所有菜单");
        result.setValue("0");
        List<MenuTreeModel> resultList = null;
        List<Menu>  menuList = menuDao.findMenuList(appId);
        List<String> checkedMenus = menuDao.findMenuIdsByRole(roleId,appId);

        //获取顶层菜单
        resultList = findChildMenuForTree("0",menuList,checkedMenus);
        for(MenuTreeModel menuFirst : resultList){
            //设置第二层菜单
            if(!menuFirst.getIsLeaf()){
                menuFirst.setData(findChildMenuForTree(menuFirst.getValue(),menuList,checkedMenus));
                if(menuFirst.getData().size() > 0){
                    for(MenuTreeModel menuSecond :menuFirst.getData()){
                        if(!menuSecond.getIsLeaf()){
                            menuSecond.setData(findChildMenuForTree(menuSecond.getValue(),menuList,checkedMenus));
                        }
                    }
                }
            }
        }
        result.setData(resultList);
        return Arrays.asList(new MenuTreeModel[]{result});
    }

    @Override
    public List<MenuModel> findMenuList(String appId, String parentMenuId) {
        return null;
    }

    @Override
    public Map<String,Object> findMenusByPage(String appId, String parentMenuId, Integer pageSize, Integer currentPage) {
        Map<String,Object> result = new HashMap<>();
        List<MenuModel> menuModelLsit = new ArrayList<>();
        List<Menu> menuList = menuDao.findMenusByPage(appId,parentMenuId,pageSize,currentPage);
        Integer menuCount = menuDao.findMenuCount(appId,parentMenuId);
        menuList.forEach(menu -> menuModelLsit.add(baseMapper.map(menu,MenuModel.class)));

        result.put("data",menuModelLsit);
        result.put("count",menuCount);
        result.put("code",0);
        result.put("msg","");

        return result;
    }

    @Override
    public String findParentIdByMenuId(String menuId) {
        return menuDao.findParentIdByMenuId(menuId);
    }

    @Override
    public List<MenuModel> findChildMenusByMenuId(String menuId) {
        return null;
    }

    @Override
    @Transactional(propagation= Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    public void createMenu(String appId, MenuModel menuModel) {
        Menu newMenu =baseMapper.map(menuModel,Menu.class);
        newMenu.setMenuId(UUID.randomUUID().toString());
        newMenu.setCreatedTime(new Date());
        newMenu.setUpdateTime(new Date());
        newMenu.setIsLeaf(true);
        String parentId = newMenu.getParentId();
        if("0".equals(parentId)){
            newMenu.setParentIds(new String[]{"0"});
        }else {
            Menu parentMenu = menuDao.findMenuById(parentId);
            List<String> parentIdList = new ArrayList(Arrays.asList(parentMenu.getParentIds()));
            parentIdList.add(parentId);
            newMenu.setParentIds(parentIdList.toArray(new String[0]));
        }

        menuDao.createMenu(newMenu);
        menuDao.correlationApp(appId,newMenu.getMenuId());
        menuDao.setMenuLeaf(newMenu.getParentId(),false);

    }

    @Override
    @Transactional(propagation= Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    public Integer deleteMenByIds(String[] menuIds) {
        int result=0;
        List<String> menuIdList;
        String parentId;
        Integer childMenuCount;
        for(String menuId : menuIds){
            parentId = menuDao.findParentIdByMenuId(menuId);

            menuIdList = menuDao.findChildMenusByParentId(menuId);
            menuIdList.add(menuId);
            menuDao.deleteMenByIds(menuIdList);
            menuDao.uncorrelationAppByMenuIds(menuIdList);

            result += menuIdList.size();

            //判断父菜单是否还存在子菜单并做相关处理
            if(!"0".equals(parentId)){
                childMenuCount = menuDao.findMenuCount(parentId);
                if(childMenuCount == 0){
                    menuDao.setMenuLeaf(parentId,true);
                }
            }
        }
        return result;
    }

    /**
     * 利用父菜单编号查询子菜单
     * @param parentId
     * @param menuList
     * @return
     */
    private List<MenuCombination> findChildMenu(String parentId, List<Menu> menuList){
        List<MenuCombination> result = new ArrayList<>();
        menuList.stream()
                .filter(menu -> parentId.equals(menu.getParentId()) && menu.getIsShow())
                .sorted(Comparator.comparing(Menu::getSortedNum))
                .forEach(menu -> result.add(baseMapper.map(menu,MenuCombination.class)));
        return result;
    }

    /**
     * 组合菜单和子菜单
     * @param menuList
     * @return
     */
    private List<MenuCombination> getMenuCombination(List<Menu>  menuList){
        List<MenuCombination> result = null;
        //获取顶层菜单
        result = findChildMenu("0",menuList);
        for(MenuCombination menuFirst : result){
            //设置第二层菜单
            if(!menuFirst.getIsLeaf()){
                menuFirst.setSubMenus(findChildMenu(menuFirst.getMenuId(),menuList));

                if(menuFirst.getSubMenus().size() > 0){
                    for(MenuCombination menuSecond :menuFirst.getSubMenus()){
                        if(!menuSecond.getIsLeaf()){
                            menuSecond.setSubMenus(findChildMenu(menuSecond.getMenuId(),menuList));
                        }
                    }
                }
            }
        }
        return result;
    }
    private List<MenuTreeModel> findChildMenuForTree(String parentId, List<Menu> menuList, List<String> checkedMenus){
        List<MenuTreeModel> result = new ArrayList<>();
        MenuTreeModel menuTreeModel;
        menuList.stream()
                .filter(menu -> parentId.equals(menu.getParentId()) && menu.getIsShow())
                .sorted(Comparator.comparing(Menu::getSortedNum))
                .forEach(menu -> {
                    result.add(baseMapper.map(menu,MenuTreeModel.class));
                });
        result.forEach(menuTreeModel1 -> {
            if(checkedMenus.size() > 0 && checkedMenus.contains(menuTreeModel1.getValue())){
                menuTreeModel1.setChecked(true);
            }
        });
        return result;
    }
}
